package com.boss.asset.service.impl;

import com.boss.apaas.dto.user.UserDTO;
import com.boss.asset.service.IRightServiceAdpter;
import com.boss.framework.exception.AppException;
import com.boss.framework.exception.AppRuntimeException;
import com.boss.sys.common.Where;
import com.boss.sys.config.ColumnConfig;
import com.boss.sys.utils.JsonUtil;
import com.boss.sys.utils.SysUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.*;

@Service
public class RightServiceAdpter implements IRightServiceAdpter {

    protected final static String ORGS = "orgs";
    protected final static String ADMDIV = "admdiv";
    protected final static String ELEMENT = "element";
    protected final static String ALL_RIGHT = "#";
    protected final static String GUID = "guid";
    protected final static String NOT_EQ = " and 1=2 ";
    protected final String RSCODE = "rscode";
    protected final String RESULT = "result";
    protected final String DATA = "data";
    protected final String RS_100000 = "100000";

    @Value("${com.boss.cse.name.permservice}")
    protected  String rightUri;
    @Value("${com.boss.cse.name.userservice}")
    protected  String userUri;

//    protected final static String GET_RIGHT_URI = "v1/right/dataright?userguid={userguid}&roleguid={roleguid}&menuguid={menuguid}&province={province}&year={year}";
    protected final static String GET_RIGHT_URI = "v2/right/dataright?userguid={userguid}&roleguid={roleguid}&province={province}&year={year}";
    protected final static String USER_ORG_URI = "v1/userorg/{userguid}/{province}/{year}";
    protected final static String ELEMENT_RIGHT_URI = "v1/right/element?userguid={userguid}&roleguid={roleguid}&elementcode={elementcode}&province={province}&year={year}";
    @Autowired
    protected RestTemplate restTemplate;
    public String getString(Object object) {
        return object == null ? "" : object.toString();
    }
    /**
     *
     * @param url
     * @param params
     * @return
     * @throws Exception
     */
    public Object getForObject(String url, Object[] params) throws Exception {
        return restTemplate.getForObject(url, Object.class, params);
    }

    /**
     *
     * @param serverName
     * @param url
     * @return
     */
    protected String getUri(String serverName,String url){
        StringBuffer uri = new StringBuffer();
        uri.append(serverName);
        if(serverName.endsWith("/")){
            if(url.startsWith("/")){
                uri.deleteCharAt(uri.length()-1).append(url);
            }else{
                uri.append(url);
            }
        }else{
            if(url.startsWith("/")){
                uri.append(url);
            }else{
                uri.append("/").append(url);
            }
        }
        return uri.toString();
    }

    /**
     *
     * @param userguid
     * @param province
     * @param year
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    @Override
    public String getRightSql(String userguid, String province, String year, String alias) throws AppRuntimeException {
       return getRightSql(userguid,null,null,province,year,alias);
    }

    /**
     *
     * @param userguid
     * @param roleguid
     * @param province
     * @param year
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    @Override
    public String getRightSql(String userguid, String roleguid, String province, String year, String alias) throws AppRuntimeException {
        return getRightSql(userguid,roleguid,null,province,year,alias);
    }

    /**
     *
     * @param userguid
     * @param menuguid
     * @param province
     * @param year
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    @Override
    public String getRightByMenuGuid(String userguid, String menuguid, String province, String year, String alias) throws AppRuntimeException {
        return getRightSql(userguid,null,menuguid,province,year,alias);
    }


    /**
     *
     * @param userguid
     * @param roleguid
     * @param menuguid
     * @param province
     * @param year
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    public String getRightSql(String userguid, String roleguid,String menuguid,String province, String year, String alias) throws AppRuntimeException {
        try {
            String uri = getUri(rightUri,GET_RIGHT_URI);
//            String resultStr = (String) restTemplate.getForObject(uri,String.class,userguid,roleguid,menuguid,province,year);
            String resultStr = (String) restTemplate.getForObject(uri,String.class,userguid,roleguid,province,year);

            Map<String,Object> result = JsonUtil.jsonToHashMap(resultStr);

//            Map<String,Object> result = JsonUtil.jsonToMap(SysUtils.nonNullStr(responseEntity));
            if(RS_100000.equals(getString(result.get(RSCODE)))){
                Map<String,Object> rightModel = null;
                if(result.get(DATA) instanceof  Map){
                    rightModel = (Map<String,Object>)result.get(DATA);
                }else if(result.get(DATA) instanceof String){
                    rightModel = JsonUtil.jsonToMap(getString(result.get(DATA)));
                }
                return parseUserRightModel(rightModel,alias);
            }else{
                throw new AppRuntimeException(getString(result.get(RESULT)));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return NOT_EQ;
        }
    }

    /**
     * 获取用户机构权限sql
     * @param userDTO
     * @param element
     * @param province
     * @param year
     * @return
     * @throws AppRuntimeException
     */
    @Override
    public Where userOrgRight(UserDTO userDTO, String element, String province, String year)throws AppRuntimeException{
        Where where = new Where();
        try {
            if (userDTO == null){
                throw new AppRuntimeException("用户已过期!");
            }
            if(StringUtils.isEmpty(element)){
                throw new AppRuntimeException("要素编码不可为空!");
            }
            if(StringUtils.isEmpty(year)){
                throw new AppRuntimeException("要素编码不可为空!");
            }
            if(StringUtils.isEmpty(element)){
                throw new AppRuntimeException("要素编码不可为空!");
            }
            String uri = getUri(userUri,USER_ORG_URI);
            Object responseEntity = getForObject(uri,new Object[]{userDTO.getGuid(),province,year});//获取用户机构权限
            Map<String,Object> result = JsonUtil.jsonToMap(SysUtils.nonNullStr(responseEntity));
            if(RS_100000.equals(getString(result.get(RSCODE)))){
                List<Map<String,Object>> userOrg = JsonUtil.jsonToList(SysUtils.nonNullStr(result.get(DATA)),Map.class);
                parseUserOrgRight(userOrg,element,where);
            }else{
                throw new AppRuntimeException(getString(result.get(RESULT)));
            }
        } catch (Exception e) {
            e.printStackTrace();
            where.and("","","1=0");
        }
        return where;
    }

    /**
     * 解析用户机构权限
     * @param userOrgs
     * @param element
     * @param where
     * @throws AppRuntimeException
     */
    private void parseUserOrgRight(List<Map<String,Object>> userOrgs, String element, Where where) throws AppException {
        Set<String> guids = new HashSet<>();
        if (!CollectionUtils.isEmpty(userOrgs)){
            for (Map<String,Object> org: userOrgs){
                if (SysUtils.nonNullStr(org.get("elementcode")).toLowerCase().equals(element.toLowerCase())){//判断机构要素编码是否一致
                    String orgGuid = SysUtils.nonNullStr(org.get("orgguid"));
                    if (!guids.contains(orgGuid)){
                        guids.add(orgGuid);
                    }
                }
            }
        }
        if (!CollectionUtils.isEmpty(guids)){
            List<String> orgLists = new ArrayList<>(guids);
            if (guids.size() == 1){
                where.and(element.toLowerCase()+ ColumnConfig.GUID, Where.EQUAL,orgLists.get(0));
            }else {
                String values = Where.getInSql(orgLists);
                where.and(element.toLowerCase() + ColumnConfig.GUID, Where.IN, values);
            }
        }else {
            where.and("","","1=0");
        }
    }

    /**
     *  权限模型解析
     * @param rightModel
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    private String parseRightModel(Map<String,Object> rightModel,String alias) throws AppRuntimeException{
        StringBuffer rightSql = new StringBuffer();
        try {
            //管理员不加业务权限
            if("-1".equals(String.valueOf(rightModel.get("usertype")))){
                rightSql.append(" and 1=1 ");
                return rightSql.toString();
            }
            Map<String,Object> userOrgs = null;
            Map<String,Object> elementRight = null;
            if(rightModel.containsKey(ORGS)&& rightModel.get(ORGS) instanceof Map){
                userOrgs = (Map<String,Object>)rightModel.get(ORGS);
            }else{
                if(rightModel.get(ORGS)!=null&&!StringUtils.isEmpty((String)rightModel.get(ORGS))){
                    userOrgs = JsonUtil.jsonToMap((String)rightModel.get(ORGS));
                }
            }
            String admdiv = (String)rightModel.get(ADMDIV);
            if(rightModel.containsKey(ELEMENT)&& rightModel.get(ELEMENT) instanceof Map){
                elementRight = (Map<String,Object>)rightModel.get(ELEMENT);
            }else{
                if(rightModel.get(ELEMENT)!=null&&!StringUtils.isEmpty((String)rightModel.get(ELEMENT))){
                    elementRight = JsonUtil.jsonToMap((String)rightModel.get(ELEMENT));
                }
            }
            if(userOrgs!=null){
                rightSql.append(getIsNullWhereSql(userOrgs,alias));
            }
            //区划权限先不加，因预算执行有问题
            /**
            rightSql.append(" and ").append(getElementName("province",false,alias)).append(" = ")
                    .append("'").append(admdiv).append("' ");
             **/
            //数据权限
            if(!SysUtils.isNullOrEmpty(elementRight)){
                rightSql.append(getIsNullWhereSql(elementRight,alias));
            }
            return rightSql.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppRuntimeException(e.getMessage());
        }
    }

    /**
     *
     * @param element
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    private String getWhereSql(Map<String,Object> element,String alias) throws AppRuntimeException{
        try {
            StringBuffer whereSql = new StringBuffer();
            for(Map.Entry<String,Object> entry:element.entrySet()){
                List<String> values;
                if(entry.getValue() instanceof List){
                    values = (List<String>) entry.getValue();
                }else{
                    values = JsonUtil.jsonToList((String)entry.getValue(),String.class);
                }
                if(values.size()==1){
                    whereSql.append(" and ").append(getElementName(entry.getKey().toLowerCase(),true,alias));
                    whereSql.append(" = ").append("'").append(values.get(0)).append("' ");
                }else{
                    whereSql.append(" and ").append(getInSql(entry.getKey().toLowerCase(),values,true,alias));
                }
            }
            return whereSql.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppRuntimeException(e.getMessage());
        }
    }


    /**
     *
     * @param element
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    private String getIsNullWhereSql(Map<String,Object> element,String alias) throws AppRuntimeException{
        try {
            StringBuffer whereSql = new StringBuffer();
            for(Map.Entry<String,Object> entry:element.entrySet()){
                List<String> values;
                if(entry.getValue() instanceof List){
                    values = (List<String>) entry.getValue();
                }else{
                    values = JsonUtil.jsonToList((String)entry.getValue(),String.class);
                }
                if (entry.getKey().equals(ALL_RIGHT)){
                    whereSql.append(" and 1=1 ");
                }else {
                    if(values.size()==1){
                        whereSql.append(" and ( ").append(getElementName(entry.getKey().toLowerCase(),true,alias));
                        whereSql.append(" = ").append("'").append(values.get(0)).append("' ");
                        whereSql.append(" or ").append(getElementName(entry.getKey().toLowerCase(),true,alias)).append(" is null ");
                        whereSql.append(" ) ");
                    }else{
                        whereSql.append(" and ( ");
                        whereSql.append(getInSql(entry.getKey().toLowerCase(),values,true,alias));
                        whereSql.append(" or ").append(getElementName(entry.getKey().toLowerCase(),true,alias)).append(" is null ");
                        whereSql.append(" ) ");
                    }
                }
            }
            return whereSql.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppRuntimeException(e.getMessage());
        }
    }


    /**
     *
     * @param fieldName
     * @param isElement
     * @param alias
     * @return
     */
    private String getElementName(String fieldName,boolean isElement,String alias){
        StringBuffer sb = new StringBuffer();
        if(StringUtils.isEmpty(alias)){
            if(isElement){
                sb.append(fieldName).append("_id");
            }else{
                sb.append(fieldName);
            }
            return sb.toString();
        }else{
            sb.append(alias).append(".");
            if(isElement){
                sb.append(fieldName).append("_id");
            }else{
                sb.append(fieldName);
            }
            return sb.toString();
        }
    }

    /**
     *
     * @param keyField
     * @param keyValues
     * @param isElement
     * @param alias
     * @return
     */
    public String getInSql(String keyField, List<String> keyValues,boolean isElement,String alias) {
        StringBuffer sb = new StringBuffer();
        if (SysUtils.isNullOrEmpty(keyValues)) {
            sb.append(getElementName(keyField,isElement,alias)).append(" in ('') ");
        } else {
            sb.append(getElementName(keyField,isElement,alias)).append(" in ( ");
            for(int i = 0; i < keyValues.size(); ++i) {
                if (i % 1000 == 0 && i != 0) {
                    sb.deleteCharAt(sb.length() - 1);
                    sb.append(") or ").append(getElementName(keyField,isElement,alias)).append(" in ( ");
                }
                sb.append("'").append((String)keyValues.get(i)).append("',");
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.append(" )");
        }
        return sb.toString();
    }

    /**
     *
     * @param keyField
     * @param keyValues
     * @param isElement
     * @param alias
     * @return
     */
    public String inSqlByGemini(String keyField, List<String> keyValues,boolean isElement,String alias) {
        StringBuffer sb = new StringBuffer();
        if (SysUtils.isNullOrEmpty(keyValues)) {
            sb.append(getElementName(keyField,isElement,alias)).append(" in ( values ('')) ");
        } else {
            sb.append(getElementName(keyField,isElement,alias)).append(" in ( values ");

            for(int i = 0; i < keyValues.size(); ++i) {
                sb.append("('").append((String)keyValues.get(i)).append("'),");
            }
            sb.deleteCharAt(sb.length() - 1);
            sb.append(" )");
        }
        return sb.toString();
    }



    /**
     *
     * @param userguid
     * @param roleguid
     * @param elementCode
     * @param province
     * @param year
     * @param alias
     * @return
     * @throws AppRuntimeException
     */
    public String getRightByElement(String userguid, String roleguid,String elementCode,String province, String year, String alias) throws AppRuntimeException {
        try {
            String uri = getUri(rightUri,ELEMENT_RIGHT_URI);
            Object responseEntity = getForObject(uri,new Object[]{userguid,roleguid,elementCode,province,year});
            Map<String,Object> result = JsonUtil.jsonToMap(SysUtils.nonNullStr(responseEntity));
            if(RS_100000.equals(getString(result.get(RSCODE)))){
                Map<String,Object> rightModel = null;
                if(result.get(DATA) instanceof  Map){
                    rightModel = (Map<String,Object>)result.get(DATA);
                }else if(result.get(DATA) instanceof String){
                    rightModel = JsonUtil.jsonToMap(getString(result.get(DATA)));
                }
                return parseUserRightModel(rightModel,alias);
            }else{
                throw new AppRuntimeException(getString(result.get(RESULT)));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return NOT_EQ;
        }
    }


    /**
     * <br>Description: 权限模型解析(新)
     * <br>Author: 张攀幸(zhangpanxing@boss.com.cn)
     * <br>Date: 2019-08-21
     * @param rightModel
     * @param alias
     * @return String
     * @throw
     */
    private String parseUserRightModel(Map<String,Object> rightModel,String alias) throws AppRuntimeException{

        StringBuffer rightSql = new StringBuffer();
        try {
            //管理员不加业务权限
            if("-1".equals(String.valueOf(rightModel.get("usertype")))){
                rightSql.append(" and 1=1 ");
                return rightSql.toString();
            }
            Map<String,Object> userOrgs = null;
            Map<String,Object> elementRight = null;
            if(rightModel.containsKey(ORGS)&& rightModel.get(ORGS) instanceof Map){
                userOrgs = (Map<String,Object>)rightModel.get(ORGS);
            }else{
                if(rightModel.get(ORGS)!=null&&!StringUtils.isEmpty((String)rightModel.get(ORGS))){
                    userOrgs = JsonUtil.jsonToMap((String)rightModel.get(ORGS));
                }
            }
            String admdiv = (String)rightModel.get(ADMDIV);
            if(rightModel.containsKey(ELEMENT)&& rightModel.get(ELEMENT) instanceof Map){
                elementRight = (Map<String,Object>)rightModel.get(ELEMENT);
            }else{
                if(rightModel.get(ELEMENT)!=null&&!StringUtils.isEmpty((String)rightModel.get(ELEMENT))){
                    elementRight = JsonUtil.jsonToMap((String)rightModel.get(ELEMENT));
                }
            }
            if(userOrgs!=null){
                rightSql.append(getIsNullWhereSql(userOrgs,alias));
            }
            //区划权限先不加，因预算执行有问题
            /**
             rightSql.append(" and ").append(getElementName("province",false,alias)).append(" = ")
             .append("'").append(admdiv).append("' ");
             **/
            //数据权限
            if(!SysUtils.isNullOrEmpty(elementRight)){
                rightSql.append(getIsNullWhereSql(elementRight,alias));
            }
            if ("".equals(rightSql.toString())){ //最终没有权限匹配
                rightSql.append(" and 1=2 ");
            }
            return rightSql.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AppRuntimeException(e.getMessage());
        }
    }
}